package com.vidmt.api.modules.sys.auth;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vidmt.api.common.utils.AES128Coder;
import com.vidmt.api.common.utils.StrUtil;
import com.vidmt.api.modules.sys.auth.PwdStrategy.ReversePwdStrategy;
import com.vidmt.api.modules.sys.auth.pwdstrategy.AesStrategy;
import com.vidmt.api.modules.sys.auth.pwdstrategy.BlowfishStrategy;
import com.vidmt.api.modules.sys.auth.pwdstrategy.HashStrategy;
import com.vidmt.api.modules.sys.auth.pwdstrategy.HashStrategy.PasswordType;
import com.vidmt.api.modules.sys.auth.pwdstrategy.PlainStrategy;
import com.vidmt.api.modules.sys.auth.pwdstrategy.ScramStrategy;

/**
 * @author xingqisheng
 */
public class AuthFactory {

	private static final Logger log = LoggerFactory.getLogger(AuthFactory.class);

	private static final Map<String, PwdStrategy> strategyMap = new HashMap<>();
	private static final PwdStrategy DB_STRATEGY = new AesStrategy();

	static {
		PwdStrategy[] strategies = { new PlainStrategy(), new HashStrategy(PasswordType.md5),
				new HashStrategy(PasswordType.sha1), new HashStrategy(PasswordType.sha256),
				new HashStrategy(PasswordType.sha512), new BlowfishStrategy(), new ScramStrategy(), new AesStrategy() };

		for (PwdStrategy strategy : strategies) {
			strategyMap.put(strategy.getAlg(), strategy);
		}
	}

	public static void main(String[] args) {
		String fmtpwd = new HashStrategy(PasswordType.sha256).encryptPassword("123456", "100001");
		String des = AES128Coder.getDefault().encrypt(StrUtil.bytesutf8(fmtpwd));
		System.out.println(fmtpwd);
		System.out.println(des);
		System.out.println(
				authenticate("1", "g3FL9akxxOXs_OteaXhtKtUHYuJQ3wt0_H3vUQQL5IRdQZ9yYRAbcynLnixJDq6gzFxVjoZAzAU="));

	}

	/**
	 * 登录时判断是否合法
	 */
	public static boolean authenticate(String password, String savedPassword) {
		savedPassword = unwrapPwd(savedPassword);
		String algName = savedPassword.substring(0, savedPassword.indexOf("#"));
		PwdStrategy strategy = strategyMap.get(algName);
		return strategy.valid(password, savedPassword);
	}

	/**
	 * 测试工具用，用来反编译密码
	 */
	public static String decodePwd(String savedPassword) {
		savedPassword = unwrapPwd(savedPassword);
		String algName = savedPassword.substring(0, savedPassword.indexOf("#"));
		PwdStrategy strategy = strategyMap.get(algName);
		if (!(strategy instanceof ReversePwdStrategy)) {
			throw new IllegalStateException("当前算法不可逆:" + algName);
		}
		ReversePwdStrategy rs = (ReversePwdStrategy) strategy;
		return rs.decryptPassword(savedPassword);
	}

	/**
	 * 存储数据库时其密码格式
	 */
	public static String fmtPwd(Long uid, String plainpwd) {
		return wrapPwd(DB_STRATEGY.encryptPassword(plainpwd, uid.toString()));
	}

	private static String wrapPwd(String ecryptpwd) {
		return AES128Coder.getDefault().encrypt(StrUtil.bytesutf8(ecryptpwd));
	}

	private static String unwrapPwd(String base64) {
		return StrUtil.newutf8(AES128Coder.getDefault().decrypt(base64));
	}
}
